/* Student: Michael Clegg
 * Instructor: Shobe
 * program 1: car simulation
 * 9/14/2013
 * This program determines the cars that perform most and least effectively (with respect to cost
 * and time) along a specific fixed route (with assumptions of gas price, stations every
 * 45 miles, 15 minutes to fuel, and mph of 35 in city and 70 on the highway) from WSU to U of Denver.
 * The idea is to convert distance to gallons using the miles per gallon values (city and highway).
 * There are stations every 45 miles, so I incremented by 45 miles. 45 mi = cityMi + hwyMi
 * 
 * NOTE: assume that the cost of the initial tank of gas should be included in the cost.
 */

import java.text.NumberFormat;
import java.util.Scanner;

public class WichitaToDenver {

    public static void main(String[] args) {

        Scanner keyboard = new Scanner(System.in);

        String con = "no";
        /** initialize while loop condition to true, "con"
         * used to ensure loop goes until user input is not "no"
         * with or without caps.
        */

        double totalDistance = 0, maxDistance = 0;
        /** totalDistance is for the total distance the cars must travel.*/

        double leastTime = 100000, leastCost = 100000;
        String leastTimeCar = "your", leastCostCar = "feet";
        /** in order: the values of the minimum time and
         * cost, the fastest car and the cheapest car */

        double mostTime = 0, mostCost = 0;
        String mostTimeCar = "walk", mostCostCar = "slowly";
        /** similar format; the maximum time and cost, respectively, and their respective cars.
         * Note that the max possible time is simply the hypothetical non-stop minimum of
         * (35*totalCityDistance + 70*totalCityDistance) plus 15*maxFuelStops. Variables defined
         * outside while loop because used afterward. Easy to remember because name <--> use
         */

        maxDistance = 1.2 + 86.8 + 416 + 12.7 + 4.7 + 0.3 + 0.6 + 33.5;
        while ( con.equalsIgnoreCase("no") ) {

            String myMake, myModel;
            double mpgCity, mpgHwy, myFuelLimit, myTime = 0, myCost = 0;
            double gasGallons, stationDistance;
            int i = 0;
            double legMiles = 1.2;
            boolean legCity  = false; /* true for city, false for Highway */
            double scratch;
            double lastGas;
            boolean failed;

            // my variables. first two remember that distance is 45 miles between each gas station
            // myTime in min, but output converted to HOURS

            System.out.println("What is the make of the car (press the space or enter key to finish typing)?:");
            myMake = keyboard.next();

            /* save "name" data temporarily with above two strings*/
            System.out.println("What is the model of the car?:");
            myModel = keyboard.next();

            System.out.println("What is the engine size (in L) of the car?:");
            scratch = keyboard.nextDouble();

            /* toss out the garbage in above two. can prove it is irrelevant data.
             * may also use "temporary" elsewhere */
            System.out.println("How many cylinders does it have?:");
            scratch = keyboard.nextDouble();

            /* this limits distance with respect to mpg. */
            System.out.println("What is the size (in gallons) of the tank?:");
            myFuelLimit = keyboard.nextDouble();

            /* this limits travel in city with respect to the remaining gas */
            System.out.println("How many miles can it travel per gallon in the city?:");
            mpgCity = keyboard.nextDouble();

            /* this limits travel on the highway with respect to the remaining gas */
            System.out.println("How many miles can it travel per gallon on the highway?:");
            mpgHwy = keyboard.nextDouble();

            lastGas = -1.0;
            myTime = 0.0;
            totalDistance = 0.0;
            gasGallons = myFuelLimit;
            myCost = myFuelLimit * 3.59; // assume initial gas cost included.
            stationDistance = 45.0;
            failed = false;


            if ( mpgCity != 0 && mpgHwy != 0 ) {
                double tempDist;

                for ( i = 0; i < 8 && !failed; i++ ) {

                    switch ( i ) {

                    // Exit WSU parking lot,
                    //(City) Travel 1.2 miles West on 21st street
                    case 0:
                        legMiles = 1.2;
                        legCity = true;
                        break;

                        //Merge onto I-135 N via ramp and head North
                        //(Highway) Travel 86.8 miles on I-135 N to Salina
                    case 1:
                        legMiles = 86.8;
                        legCity = false;
                        break;

                        //Take exit 95B and merge onto I-70 W via ramp and head West
                        //(Highway) Travel 416 miles on I-70 W to Denver
                    case 2:
                        legMiles = 416;
                        legCity = false;
                        break;

                        //Take exit 282 and merge onto I-225 S via ramp and head South
                        //(Highway) Travel 12.7 miles on I-225 S to exit 1B for I-25
                    case 3:
                        legMiles = 12.7;
                        legCity = false;
                        break;

                        //Take exit 1B and merge onto I-25 N via ramp and head North
                        //(Highway) Travel 4.7 miles on I-25 N to exit 205 for University Blvd
                    case 4:
                        legMiles = 4.7;
                        legCity = false;
                        break;

                        //Take exit 205 for University Blvd and follow signs to S University Blvd
                        //(City) Travel 0.3 miles on University Blvd to S University Blvd
                    case 5:
                        legMiles = 0.3;
                        legCity = true;
                        lastGas = 0.3 + 0.6 + 33.5; /* no more gas stations after this corner */
                        break;

                        //Turn left onto S University Blvd and head to the University
                        //(City) Travel 0.6 miles to The University of Denver
                    case 6:
                        legMiles = 0.6;
                        legCity = true;
                        break;

                        //Arrive at University of Denver parking lot and begin the car shark attack
                        //(City) Travel 33.5 miles doing circles in the parking lot before finding a parking spot
                    case 7:
                        legMiles = 33.5;
                        legCity = true;
                        break;

                    default:
                        break;
                    }

                    /*
                     *  Each leg may have multiple stations, need to check all stations
                     *  simulate each 45 mile segment of the leg to check iteratively
                     */
                    tempDist = legMiles;
                    while ( tempDist > 0 ) {

                        /* If there is a station somewhere check for gas */
                        if ( stationDistance < legMiles ) {
                            // Do we need to stop for gas? assume we can make it to next station.
                            // can we make it to station after that?
                            // mpg * gasGallons = miles left
                            // if distance it needs to travel is greater than max distance then we need to stop
                            // (be conservative and use lowest MPG)

                            if ( lastGas <= 0.0 ) {

                                if ( stationDistance + 45 >= (legCity ? mpgCity:mpgHwy) * gasGallons ) {
                                    // need to stop at this station add 15 minutes, refuel
                                	
                                    myTime += 15.0;
                                    myCost += 3.59 * (myFuelLimit - gasGallons);
                                    
                                    gasGallons -= (legCity) ? stationDistance / mpgCity : stationDistance / mpgHwy;
                                    gasGallons = myFuelLimit;

                                    /* we travelled stationDistance miles to the station and filled up */
                                    totalDistance += stationDistance;
                                    tempDist -= stationDistance;
                                    
                                    /* next station must be 45 miles away */
                                    stationDistance = 45;
                                }

                            } else {

                                if ( lastGas >= ((mpgCity < mpgHwy) ? mpgCity:mpgHwy) * gasGallons ) {
                                    // need to stop at this station add 15 minutes, refuel
                                    myTime += 15.0;
                                    myCost += 3.59 * (myFuelLimit - gasGallons);
                                   
                                    gasGallons -= (legCity) ? legMiles / mpgCity : legMiles / mpgHwy;
                                    gasGallons = myFuelLimit;

                                    /* special case - we know we are only travelling the .3 miles to the corner */
                                    totalDistance += legMiles;
                                    tempDist -= legMiles;
                                }
                                /* we know we can make it don't check again */
                                lastGas = 0.001;

                            }


                        }

                        /* Travel the rest of the segment or to next station check */
                        if ( tempDist < 45.0 ) {
                            stationDistance -= tempDist; /* this will be the distance to the station on the next leg */
                            totalDistance += tempDist;

                            if ( stationDistance <= 0.0 ) {
                                stationDistance += 45.0;
                            }
                            gasGallons -= (legCity) ? tempDist / mpgCity : tempDist / mpgHwy;

                            if ( gasGallons <= 0 ) {
                                System.out.printf("ERROR1 - %s %s needs %f more gallons%n", myMake, myModel, -gasGallons);
                                failed = true;
                                break;
                            }

                        } else {
                            /* OK, just go another 45 miles then loop back */
                            /* stationDistance the distance will remain the same */
                            totalDistance += 45.0;
                            gasGallons -= (legCity) ? 45.0 / mpgCity : 45.0 / mpgHwy;

                            if ( gasGallons <= 0 ) {
                                System.out.printf("ERROR2 - %s %s needs %f more gallons%n", myMake, myModel, -gasGallons);
                                failed = true;
                                break;
                            }
                        }

                        // calculate next station decision
                        tempDist -= 45.0;
                    } /* end tempDist (travel tracking) loop */
                    /*
                     * Calculate amount of time traveled
                     * TimeIncMinutes = Miles / MPH * 60 HoursPerMinute
                     */
                    myTime += legMiles / ((legCity) ? 30 : 70) * 60;
                } /* end trip for loop */

            } /* end input validity check */

            //if (failed)
            //System.out.printf("ERROR3 - needs %f more gallons%n", -gasGallons);

            if ( failed == false ) {
                /* Eliminate remaining gallons from cost */
                myCost -= gasGallons * 3.59;

                if ( leastTime > myTime ) {
                    leastTime = myTime;
                    leastTimeCar = myMake + " " + myModel;
                } // save fastest car and its time and convert time to hours (myTime in min.)

                if ( mostTime < myTime ) {
                    mostTime = myTime;
                    mostTimeCar = myMake + " " + myModel;
                } // same here for slowest

                if ( mostCost < myCost ) {
                    mostCost = myCost;
                    mostCostCar = myMake + " " + myModel;
                }

                if ( leastCost > myCost ) {
                    leastCost = myCost;
                    leastCostCar = myMake + " " + myModel;
                }

            } else {
                System.out.printf("%s %s ran out of gas before %f miles%n", myMake, myModel, totalDistance);
            }

            // Ask if we wish to enter another car ...
            System.out.println("Is that all? (enter 'no' to continue):");
            con = keyboard.next();


        } /* end of input loop */

        System.out.printf("All viable cars must travel %6.2f miles.%n", maxDistance);

        System.out.printf("The %s is fastest with a travel time", leastTimeCar);
        System.out.printf(" of %6.2f hours.%n", leastTime/60);

        System.out.printf("The %s is slowest with a travel time", mostTimeCar);
        System.out.printf(" of %6.2f hours.%n", mostTime/60);

        NumberFormat moneyFormater =
        NumberFormat.getCurrencyInstance();

        System.out.printf("The %s costs the least with a total of ", leastCostCar);
        System.out.println(moneyFormater.format(leastCost));

        System.out.printf("The %s costs the most with a total of ", mostCostCar);
        System.out.println(moneyFormater.format(mostCost));


    }
}


